/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.iec.edp.caf.commons.layeringcache.setting;

import io.iec.edp.caf.commons.layeringcache.serializer.RedisDataSerializer;
import io.iec.edp.caf.commons.layeringcache.support.ExpireMode;
import io.iec.edp.caf.commons.utils.StringUtils;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.util.concurrent.TimeUnit;

/**
 * 多级缓存配置项
 * <p>
 * todo builder 多参构造
 */
@Deprecated
public class LayeringCacheSetting implements Serializable {
    private static final String SPLIT = "-";

    private static LayeringCacheSetting defaultSetting;
    /**
     * 内部缓存名，由[一级缓存有效时间-二级缓存有效时间-二级缓存自动刷新时间]组成
     */
    private String internalKey;

    /**
     * 描述，数据监控页面使用
     */
    private String depict = "";

    /**
     * 是否使用一级缓存
     */
    boolean useFirstCache = true;

    /**
     * 是否使用二级缓存
     */
    boolean useSecondCache = true;

    /**
     * 一级缓存配置
     */
    private FirstCacheSetting firstCacheSetting;

    /**
     * 二级缓存配置
     */
    private SecondaryCacheSetting secondaryCacheSetting;

    public LayeringCacheSetting() {
    }

    public LayeringCacheSetting(FirstCacheSetting firstCacheSetting, SecondaryCacheSetting secondaryCacheSetting) {
        this(firstCacheSetting, secondaryCacheSetting, StringUtils.EMPTY);
    }

    public LayeringCacheSetting(FirstCacheSetting firstCacheSetting, SecondaryCacheSetting secondaryCacheSetting,
                                String depict) {
        Assert.isTrue(firstCacheSetting != null || secondaryCacheSetting != null, "请至少开启一级缓存");

        if (firstCacheSetting == null) {
            this.useFirstCache = false;
        }

        if (secondaryCacheSetting == null) {
            this.useSecondCache = false;
        }

        this.firstCacheSetting = firstCacheSetting;
        this.secondaryCacheSetting = secondaryCacheSetting;
        this.depict = depict;
        internalKey();
    }

    public static LayeringCacheSetting getDefaultCacheSetting() {
        if (defaultSetting == null) {
            defaultSetting = new LayeringCacheSetting(new FirstCacheSetting(10, 500, 1, TimeUnit.MINUTES, ExpireMode.WRITE),
                    new SecondaryCacheSetting(5, 1, TimeUnit.MINUTES, false, false, 10), "default");
        }

        return defaultSetting;
    }

    private void internalKey() {
        // 一级缓存有效时间-二级缓存有效时间-二级缓存自动刷新时间
        StringBuilder sb = new StringBuilder();
        if (firstCacheSetting != null) {
            sb.append(firstCacheSetting.getTimeUnit().toMillis(firstCacheSetting.getExpireTime()));
        }
        sb.append(SPLIT);
        if (secondaryCacheSetting != null) {
            sb.append(secondaryCacheSetting.getTimeUnit().toMillis(secondaryCacheSetting.getExpiration()));
            sb.append(SPLIT);
            sb.append(secondaryCacheSetting.getTimeUnit().toMillis(secondaryCacheSetting.getPreloadTime()));
        }

        internalKey = sb.toString();
    }

    public FirstCacheSetting getFirstCacheSetting() {
        return firstCacheSetting;
    }

    public SecondaryCacheSetting getSecondaryCacheSetting() {
        return secondaryCacheSetting;
    }

    public String getInternalKey() {
        return internalKey;
    }

    public boolean isUseFirstCache() {
        return useFirstCache;
    }

    public void setUseFirstCache(boolean useFirstCache) {
        this.useFirstCache = useFirstCache;
    }

    public boolean isUseSecondCache() {
        return useSecondCache;
    }

    public void setUseSecondCache(boolean useSecondCache) {
        this.useSecondCache = useSecondCache;
    }

    public void setFirstCacheSetting(FirstCacheSetting firstCacheSetting) {
        this.firstCacheSetting = firstCacheSetting;
    }

    public void setSecondaryCacheSetting(SecondaryCacheSetting secondaryCacheSetting) {
        this.secondaryCacheSetting = secondaryCacheSetting;
    }

    public String getDepict() {
        return depict;
    }

    public void setDepict(String depict) {
        this.depict = depict;
    }

    /**
     * 内部构造器 提供可选参数化构造方式
     */
    public static class Builder {
        private final FirstCacheSetting firstCacheSetting = new FirstCacheSetting();
        private final SecondaryCacheSetting secondaryCacheSetting = new SecondaryCacheSetting();

        private boolean useFirstCache = true;
        private boolean useSecondCache = true;
        private String depict = "";

        public Builder() {
        }

        public Builder enableFirstCache() {
            this.useFirstCache = true;
            return this;
        }

        public Builder disableFirstCache() {
            this.useFirstCache = false;
            return this;
        }

        public Builder enableSecondCache() {
            this.useSecondCache = true;
            return this;
        }

        public Builder disableSecondCache() {
            this.useSecondCache = false;
            return this;
        }

        public Builder firstCacheInitialCapacity(int value) {
            this.firstCacheSetting.setInitialCapacity(value);
            return this;
        }

        public Builder firstCacheMaximumSize(int value) {
            this.firstCacheSetting.setMaximumSize(value);
            return this;
        }

        public Builder firstCacheExpireTime(int value) {
            this.firstCacheSetting.setExpireTime(value);
            return this;
        }

        public Builder firstCacheTimeUnit(TimeUnit timeUnit) {
            this.firstCacheSetting.setTimeUnit(timeUnit);
            return this;
        }

        public Builder firstCacheExpireMode(ExpireMode expireMode) {
            this.firstCacheSetting.setExpireMode(expireMode);
            return this;
        }

        public Builder secondCacheExpireTime(long value) {
            this.secondaryCacheSetting.setExpiration(value);
            this.secondaryCacheSetting.setPreloadTime(value / 5);
            return this;
        }

        public Builder secondCachePreloadTime(long value) {
            this.secondaryCacheSetting.setPreloadTime(value);
            return this;
        }

        public Builder secondCacheTimeUnit(TimeUnit timeUnit) {
            this.secondaryCacheSetting.setTimeUnit(timeUnit);
            return this;
        }

        public Builder forceFresh(boolean value) {
            this.secondaryCacheSetting.setForceRefresh(value);
            return this;
        }

        public Builder allowNullValue(boolean value) {
            this.secondaryCacheSetting.setAllowNullValue(value);
            return this;
        }

        public Builder magnification(int value) {
            this.secondaryCacheSetting.setMagnification(value);
            return this;
        }

        public Builder dataSerializer(RedisDataSerializer redisDataSerializer) {
            this.secondaryCacheSetting.setRedisDataSerializer(redisDataSerializer);
            return this;
        }

        public Builder depict(String depict) {
            this.depict = depict;
            return this;
        }

        public LayeringCacheSetting build() {
            FirstCacheSetting firstCacheSetting = this.useFirstCache ? this.firstCacheSetting : null;
            SecondaryCacheSetting secondaryCacheSetting = this.useSecondCache ? this.secondaryCacheSetting : null;
            return new LayeringCacheSetting(firstCacheSetting, secondaryCacheSetting, depict);
        }
    }
}
